Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial lightning network node implementation #1103

Merged
merged 17 commits into from
Oct 18, 2021
Merged

Partial lightning network node implementation #1103

merged 17 commits into from
Oct 18, 2021

Conversation

shamardy
Copy link
Collaborator

This is the first of multiple PRs for lightning integration in mm2 #1045

Some notes:

  • There are multiple todos left in the code that should be done with the next phase which is implementing channels opening as they can be better tested after having channels.
  • I used dispatcher_legacy for the enable_lightning method for now as I am waiting to see how it will fit with enable_v2 in the future to move it to dispacher_v2
  • This is the guide I used for a big part of this code https://lightningdevkit.org/tutorials/build_a_node_in_rust/ it can help in understanding the code better
  • I implemented the node for electrum only for now as part of the PoC. In the future, I will implement the native mode too but I postponed it for now because I will need to run the bitcoin daemon in Regtest mode for it.

mm2src/coins/lightning.rs Outdated Show resolved Hide resolved
mm2src/coins/lightning.rs Outdated Show resolved Hide resolved
Copy link
Member

@artemii235 artemii235 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I have a few questions and comments.

// The current time is used to derive random numbers from the seed where required, to ensure all random generation is unique across restarts.
let cur = try_s!(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH));

// Initialize the KeysManager
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we initialize BTC and LTC lightning at the same time, can this cause any problems or even be insecure?

Copy link
Collaborator Author

@shamardy shamardy Oct 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't thought about LTC lightning yet as it's not supported by the rust-lightning library. https://github.com/rust-bitcoin/rust-lightning/blob/fe8c10db95124e3238b7469bdabb00afc7c5bdd6/lightning-invoice/src/lib.rs#L328-L345.
But as I understand for LTC or any other coin (some other UTXO coins are currently experimenting with lightning e.g. Bitcoin Gold) we will have to run enable lightning again with a different port and configs so it will have a different KeysManager. I guess this https://github.com/KomodoPlatform/atomicDEX-API/blob/ad87f483cc5199851a781c5b99a1bda341f75ecb/mm2src/common/mm_ctx.rs#L98 will have to be changed to even run tBTC and BTC together in lightning

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will have to run enable lightning again with a different port and configs so it will have a different KeysManager

If these managers will run at the exactly same time, will they generate the same keys/secrets? If yes, are these secrets then revealed? Can this cause potential compromise of the LTC or another coin channel using information about the BTC channel?

It might be very hard to catch the same nanoseconds value, but do all the OSes we use support nanoseconds timestamp precision? According to https://doc.rust-lang.org/std/time/struct.Duration.html: If the underlying system does not support nanosecond-level precision, APIs binding a system timeout will typically round up the number of nanoseconds.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these managers will run at the exactly same time, will they generate the same keys/secrets? If yes, are these secrets then revealed? Can this cause potential compromise of the LTC or another coin channel using information about the BTC channel?

I can't find an instance in the LDK code where these secrets are revealed so this should be alright. But for safety and to ensure uniqueness maybe we can keep the last generated value of SystemTime in the ctx and check when enabling 2 or more coins, this will require locking which might be even enough without storing the last value to ensure let cur = try_s!(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)); is unique as it will never run at the same time in different threads.

It might be very hard to catch the same nanoseconds value, but do all the OSes we use support nanoseconds timestamp precision? According to https://doc.rust-lang.org/std/time/struct.Duration.html: If the underlying system does not support nanosecond-level precision, APIs binding a system timeout will typically round up the number of nanoseconds.

Only Linux supports nanoseconds precision for the SystemTime::now() call according to the underlying system calls, for Windows and Darwin the precision is in microseconds. So for the above suggestion of locking the ctx when doing the SystemTime::now() it might be sufficient to wait a minimum of one microsecond before unlocking it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add this to the TODO in the code when supporting multiple coins. I will keep this https://github.com/KomodoPlatform/atomicDEX-API/blob/ad87f483cc5199851a781c5b99a1bda341f75ecb/mm2src/common/mm_ctx.rs#L98 for now which means only one coin can be enabled.

));

// Initialize p2p networking
let listener = try_s!(TcpListener::bind(format!("0.0.0.0:{}", conf.ln_peer_listening_port)).await);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If our node is behind the NAT, can this affect Lightning functionality?

Copy link
Collaborator Author

@shamardy shamardy Oct 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure as no real p2p functionality is working right now. It will appear in the next stage of the implementation as all lightning events require p2p messaging, and my computer is behind NAT so I can test it more extensively then. Maybe I should add a TODO note here to not forget.
I can also see that NAT Traversal is available for other LN implementations but can't find any mention of it in rust-lightning docs.
I found a mistake I made also, I think I need to send the external IP address here even if the node can't bind on it https://github.com/KomodoPlatform/atomicDEX-API/blob/ad87f483cc5199851a781c5b99a1bda341f75ecb/mm2src/coins/lightning.rs#L401-L405 I didn't do this as they said in the documentation that an empty IP Vec is alright https://github.com/rust-bitcoin/rust-lightning/blob/fe8c10db95124e3238b7469bdabb00afc7c5bdd6/lightning/src/ln/channelmanager.rs#L2370 but if the node is behind NAT other nodes still need the external IP address to connect to it, and the IP is also needed for the node to appear in the network graph as I can see from other parts of the rust-lightning library.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the mistake I mentioned above in the latest commits

mm2src/coins/lightning.rs Outdated Show resolved Hide resolved
}

impl BroadcasterInterface for ElectrumClient {
fn broadcast_transaction(&self, tx: &Transaction) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit sad that they assume a synchronous interface for this 🙁

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is intended as they leave you the choice to run these functions in asynchronous code through other interfaces. For the broadcast_transaction function for instance, when a new best block is updated for the channel manager https://github.com/KomodoPlatform/atomicDEX-API/blob/ad87f483cc5199851a781c5b99a1bda341f75ecb/mm2src/coins/lightning.rs#L384 if it's required to claim on-chain channel funds for some reason as this case https://github.com/rust-bitcoin/rust-lightning/blob/fe8c10db95124e3238b7469bdabb00afc7c5bdd6/lightning/src/chain/onchaintx.rs#L486, broadcast_transaction is run in the best_block_update thread away from the p2p networking and node announcement. The only problem I see is if for the same new best block more than one on-chain transaction needs to be broadcasted then they will be broadcasted synchronously inside the best_block_update thread but this is very rare but would have been solved if broadcast_transaction was async.

Copy link
Member

@artemii235 artemii235 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, thanks! The questions I still have are not blockers.

@Milerius Milerius self-requested a review October 16, 2021 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants